package com.jeasonzhao.web;

import com.jeasonzhao.commons.json.JSONArray;
import com.jeasonzhao.commons.json.JSONClass;
import com.jeasonzhao.commons.json.JSONNode;
import com.jeasonzhao.commons.utils.Algorithms;
import com.jeasonzhao.commons.xml.XMLHelper;
import com.jeasonzhao.commons.xml.XMLNode;
import com.jeasonzhao.commons.json.JSONParser;
import com.jeasonzhao.commons.json.JSONException;
import com.jeasonzhao.commons.parser.lex.LexException;
import com.jeasonzhao.commons.xml.XMLException;
import com.jeasonzhao.model.ModelHelper;
import com.jeasonzhao.model.ModelException;
import com.jeasonzhao.commons.utils.ConvertEx;
import com.jeasonzhao.commons.annotation.Dictionary;
import com.jeasonzhao.commons.annotation.Title;

public class ToolbarItemCollection extends java.util.Vector<ToolbarItem>
{
    private static final long serialVersionUID = 1L;

    public ToolbarItemCollection()
    {
        super();
    }

    public static ToolbarItemCollection from(String str)
        throws JSONException,XMLException,LexException
    {
        if(Algorithms.isEmpty(str))
        {
            return null;
        }
        if(Algorithms.isXmlString(str))
        {
            return from(XMLHelper.fromString(str));
        }
        else if(Algorithms.isJSONString(str))
        {
            return from(JSONParser.parse(str));
        }
        else
        {
            return fromFormatedString(str);
        }
    }

    private static ToolbarItemCollection fromFormatedString(String str)
        throws LexException
    {
        java.util.ArrayList < java.util.ArrayList < String >> rows = JSONNode.simpleStringParse(str);
        if(null == rows)
        {
            return null;
        }
        ToolbarItemCollection ret = new ToolbarItemCollection();
        for(java.util.ArrayList<String> r : rows)
        {
            String text = r.size() > 0 ? r.get(0) : null;
            String icon = r.size() > 1 ? r.get(1) : null;
            String handler = r.size() > 2 ? r.get(2) : null;
            String selected = r.size() > 3 ? r.get(3) : null;
            if(Algorithms.isEmpty(text))
            {
                continue;
            }
            ToolbarItem itm = new ToolbarItem();
            itm.setText(text);
            itm.setIcon(icon);
            itm.setHandler(handler);
            itm.setSelected(ConvertEx.toBool(selected) || "selected".equalsIgnoreCase(selected));
            ret.add(itm);
        }
        return ret;
    }

    public static final ToolbarItemCollection from(Class<?> cls,boolean ordinal)
        throws IllegalAccessException,IllegalArgumentException
    {
        ToolbarItemCollection ret = new ToolbarItemCollection();
        if(null == cls)
        {
            return null;
        }
        else if(cls.isEnum())
        {
            for(java.lang.reflect.Field f : cls.getFields())
            {
                if(java.lang.reflect.Modifier.isStatic(f.getModifiers())
                   && java.lang.reflect.Modifier.isPublic(f.getModifiers()))
                {
                    Enum<?> e = (Enum<?>) f.get(null);
                    Title t = f.getAnnotation(Title.class);
                    Dictionary d = f.getAnnotation(Dictionary.class);
                    String name = null == t ? (null == d ? f.getName() : d.title()) : t.value();
                    if(null == name || name.trim().length() < 1)
                    {
                        name = f.getName();
                    }
                    String id = ordinal ? ("" + e.ordinal()) : e.name();
                    ret.add(new ToolbarItem()
                            .setId(id)
                            .setText(name));
                }
            }
        }
        else
        {
            for(java.lang.reflect.Field f : cls.getFields())
            {
                if(java.lang.reflect.Modifier.isStatic(f.getModifiers())
                   && java.lang.reflect.Modifier.isPublic(f.getModifiers()))
                {
                    Object e = f.get(null);
                    Title t = f.getAnnotation(Title.class);
                    Dictionary d = f.getAnnotation(Dictionary.class);
                    String name = null == t ? (null == d ? f.getName() : d.title()) : t.value();
                    if(null == name || name.trim().length() < 1)
                    {
                        name = f.getName();
                    }
                    String id = ordinal || null == e ? f.getName() : e.toString();
                    ret.add(new ToolbarItem()
                            .setId(id)
                            .setText(name));
                }
            }
        }
        return ret;

    }

    public static ToolbarItemCollection from(JSONNode node)
    {
        if(node == null)
        {
            return null;
        }
        else
        {
            ToolbarItemCollection ret = new ToolbarItemCollection();
            if(node.isJSONArray())
            {
                for(JSONNode subNodeFromAry : ((JSONArray) node).items())
                {
                    if(subNodeFromAry.isJSONClass())
                    {
                        ret.add(ToolbarItem.from(null,(JSONClass) subNodeFromAry));
                    }
                }
            }
            else if(node.isJSONClass())
            {
                ret.add(ToolbarItem.from(null,(JSONClass) node));
            }
            return ret;
        }
    }

    public static ToolbarItemCollection from(XMLNode node)
    {
        if(null == node)
        {
            return null;
        }
        else
        {
            ToolbarItemCollection coll = new ToolbarItemCollection();
            for(XMLNode sub : node.selectNodes())
            {
                coll.add(ToolbarItem.from(null,sub));
            }
            return coll;
        }
    }

    public static <T> ToolbarItemCollection from(Iterable<T> it,final String idfield,final String parentidfield
        ,final String textfield,Object idOfRoot)
        throws ModelException
    {
        if(null == it)
        {
            return null;
        }
        IToolbarItemIterator<T> its = new IToolbarItemIterator<T>()
        {
            public Object getId(T obj)
                throws Exception
            {
                return ModelHelper.getInstance().getFieldValue(obj,idfield,"id","code","key");
            }

            public Object getParentId(T obj)
                throws Exception
            {
                return ModelHelper.getInstance().getFieldValue(obj,parentidfield,"parentId","parent","parentCode");
            }

            public String getText(T obj)
                throws Exception
            {
                return Algorithms.oneOfNotNull(Algorithms.toString(ModelHelper.getInstance().getFieldValue(obj,textfield,"name","text","title"))
                                               ,Algorithms.toString(obj));
            }
        };
        return fromList(it,its,idOfRoot);
    }

    public static <T> ToolbarItemCollection from(Iterable<T> it,IToolbarItemIterator<T> its,Object idOfRoot)
        throws ModelException
    {
        if(null == it || null == its)
        {
            return null;
        }
        return fromList(it,its,idOfRoot);
    }

    private static final <T> ToolbarItemCollection fromList(Iterable<T> it,IToolbarItemIterator<T> its,Object rootId)
        throws ModelException
    {
        try
        {
            ToolbarItemCollection ret = new ToolbarItemCollection();
            for(java.util.Iterator<T> i = it.iterator();i.hasNext();)
            {
                T obj = i.next();
                if(null == obj)
                {
                    continue;
                }
                Object id = its.getId(obj);
                Object pid = its.getParentId(obj);
                if(id == null && pid == null)
                {
                    i.remove();
                    continue;
                }
                if((null == rootId && pid == null)
                   || (null != rootId && rootId.equals(pid)))
                {
                    ToolbarItem item = ToolbarItem.from(null,(JSONClass) ModelHelper.getInstance().toJSON(obj));
                    item.setId(Algorithms.toString(id));
                    item.setTag(id);
                    item.setText(Algorithms.oneOfNotNull(its.getText(obj),Algorithms.toString(obj)));
                    i.remove();
                    ret.add(item);
                }
            }
            for(ToolbarItem item : ret)
            {
                item.setItems(fromList(it,its,item.getTag()));
            }
            return ret;
        }
        catch(Exception ex)
        {
            throw new ModelException.FieldValueHandleError(null,null,ex);
        }
    }

    public String toString()
    {
        return toString(0);
    }

    protected String toString(int nLevel)
    {
        String prefix = Algorithms.repeatString("    ",nLevel);
        StringBuffer buf = new StringBuffer();
        for(ToolbarItem item : this)
        {
            buf.append(prefix + item.getId() + "=" + item.getText());
            buf.append("\r\n");
            buf.append(item.getItems().toString(nLevel + 1));
        }
        return buf.toString();
    }

    public ToolbarItemCollection cleanSelection()
    {
        for(ToolbarItem item : this)
        {
            item.setSelected(false);
            if(null != item.getItems())
            {
                item.getItems().cleanSelection();
            }
        }
        return this;
    }

    public ToolbarItemCollection cleanState()
    {
        for(ToolbarItem item : this)
        {
            item.setState(null);
            if(null != item.getItems())
            {
                item.getItems().cleanState();
            }
        }
        return this;
    }

    public ToolbarItem findItemById(String id)
    {
        if(Algorithms.isEmpty(id))
        {
            return null;
        }
        for(ToolbarItem item : this)
        {
            if(null != item && id.equals(item.getId()))
            {
                return item;
            }
            else
            {
                ToolbarItem sub = item == null || item.getItems() == null
                    ? null : item.getItems().findItemById(id);
                if(null != sub)
                {
                    return sub;
                }
            }
        }
        return null;
    }

    public java.util.Vector<ToolbarItem> listAllItemsWithoutCascaded()
    {
        java.util.Vector<ToolbarItem> ret = new java.util.Vector<ToolbarItem>();
        return listAllItemsWithoutCascaded(ret);
    }

    private java.util.Vector<ToolbarItem> listAllItemsWithoutCascaded(java.util.Vector<ToolbarItem> ret)
    {
        for(ToolbarItem item : this)
        {
            ret.add(item);
            if(null != item.getItems())
            {
                item.getItems().listAllItemsWithoutCascaded(ret);
            }
        }
        return ret;
    }

//    public static void main(String[] argvs)
//        throws ModelException
//    {
//        System.out.println("ZZ" +
//                           ToolbarItemCollection.from(RegionHelper.getAllSubRegions("11",true),
//            new IToolbarItemIterator<Region>()
//        {
//            public Object getId(Region region)
//            {
//                return region.getCode();
//            }
//
//            public Object getParentId(Region region)
//            {
//                return region.getParentCode();
//            }
//
//            public String getText(Region region)
//            {
//                return region.getName();
//            }
//        }
//        ,"[CHINA]")
//            .toString()
//            );
//    }
}
